﻿#ifndef _EASY_EPOLL_CLIENT_H_
#define _EASY_EPOLL_CLIENT_H_

#if __linux__

#include "EasyTcpClient.h"
#include "CELLEpoll.hpp"

class EasyEpollClient : public EasyTcpClient
{
public:
	virtual ~EasyEpollClient()
	{
		EasyTcpClient::Close();
	}

	// 发送数据
	// 处理网络消息
	virtual bool OnRun(int microseconds) override
	{
		if (IsRun())
		{
			if (_pClient->needWrite())
			{
				// 如果客户端有数据可发送，那么就检测可写
				_ep.ctl(EPOLL_CTL_MOD, _pClient, EPOLLOUT | EPOLLIN);
			}
			else
			{
				_ep.ctl(EPOLL_CTL_MOD, _pClient, EPOLLIN);
			}

			int ret = _ep.wait(microseconds);
			if (ret < 0)
			{
				CELLLog_pError("EasyEpollClient::OnRun");
				return false;
			}
			else if (ret == 0)
			{
				return true;
			}

			auto events = _ep.events();
			for (int i = 0; i < ret; ++i)
			{
				// 客户端可读
				if (events[i].events & EPOLLIN)
				{
					if (RecvData() == SOCKET_ERROR)
					{
						CELLLog_Error("<sock=%d> OnRun epoll RecvData error exit on line %d", (int)_pClient->sockfd(), __LINE__);
						Close();
						continue;
					}
				}

				// 客户端可写
				if (events[i].events & EPOLLOUT)
				{
					if (pClient->SendDataReal() == SOCKET_ERROR)
					{
						CELLLog_Error("<sock=%d> OnRun epoll SendDataReal error exit on line %d", (int)_pClient->sockfd(), __LINE__);
						Close();
					}
				}
			}
			return true;
		}
		return false;
	}
private:
	virtual void OnInitSocket() override
	{
		// 初始化本客户端时创建epoll根节点
		_ep.create(1);
		_ep.ctl(EPOLL_CTL_ADD, _pClient->sockfd(), EPOLLIN);
	}

	virtual void OnConnect() override;

	virtual void Close() override
	{
		_ep.destory();
		EasyTcpClient::Close();
	}

	CELLEpoll _ep;
};

#endif // #if __linux__

#endif // #ifndef _EASY_EPOLL_CLIENT_H_
